<template>
  <!-- 顶栏 -->
  <Toolbar>
    <template #left>
      <ElUpload
        class="op-item"
        :show-file-list="false"
        :before-upload="handleBeforeUpload"
      >
        <ElButton type="primary" icon="Upload">文件上传</ElButton>
      </ElUpload>

      <ElButton
        v-if="key === KEY_TYPE.ALL"
        class="op-item"
        @click="openDialog('create')"
      >
        新建文件夹</ElButton
      >
      <ElButton class="op-item" @click="handleBatchDelete">批量删除</ElButton>
      <ElButton class="op-item" @click="handleBatchMove">批量移动</ElButton>

      <ElInput
        class="search-panel"
        v-model="tableOptions.options.params.filename"
        placeholder="请输入文件名称搜索"
      >
        <template #append>
          <ElButton icon="Search" @click="tableRef.refreshGrid()"></ElButton>
        </template>
      </ElInput>
    </template>
    <template #right>
      <ElPopover
        v-model:visible="visible"
        placement="bottom-end"
        width="800"
        trigger="click"
      >
        <template #reference>
          <div style="display: flex; align-items: center; cursor: pointer">
            <ElIcon color="#8eaee4" size="14">
              <Switch />
            </ElIcon>
            <p style="margin-left: 10px; color: #8eaee4; font-size: 14px">
              上传列表
            </p>
             
          </div>
        </template>
        <template #default>
          <div class="upload-popover">
            <header class="upload-header">
              上传任务<span class="upload-subtitle"
                >（仅展示本次上传任务）</span
              >
            </header>
            <div class="upload-divider"></div>
            <div class="upload-body">
              <UploadItem
                v-for="item in Array.from(uploadMap.values())"
                :key="item.id"
                :file="item"
                :progress="item.progress"
                @clear="handleClear"
                @pause="handlePause"
                @cancel="handleCancel"
                @retry="handleRetry"
              />
            </div>
          </div>
        </template>
      </ElPopover>
    </template>
  </Toolbar>
  <!-- 面包屑 -->
  <BreadCrumb
    v-if="key === KEY_TYPE.ALL"
    :folder-stack="folderStack"
    @navigate="handleNavigate"
  ></BreadCrumb>
  <!-- 文件列表 -->
  <Table
    ref="tableRef"
    :options="tableOptions.options"
    :columns="tableOptions.columns"
  >
    <template #filename="{ row }">
      <div v-if="row.category !== 'folder'" class="file-item">
        <ElIcon size="14">
          <Document />
        </ElIcon>
        <span
          style="margin-left: 10px; cursor: pointer"
          @click="handlePreview(row)"
          >{{ row.filename }}</span
        >
      </div>
      <div v-else-if="row.category === 'folder'">
        <ElIcon size="14">
          <Folder />
        </ElIcon>
        <ElLink
          style="margin-left: 10px; font-weight: 400"
          @click="openFolder(row)"
          >{{ row.filename }}</ElLink
        >
      </div>
    </template>
    <template #action="{ row }">
      <ElLink
        class="mr10"
        type="primary"
        :disabled="row.category === 'folder'"
        @click="handleDownload(row)"
        >下载</ElLink
      >

      <ElPopconfirm
        confirm-button-text="是"
        cancel-button-text="否"
        :icon="InfoFilled"
        title="是否删除?"
        @confirm="handleDelete(row.id)"
      >
        <template #reference>
          <ElLink class="mr10" type="primary">删除</ElLink>
        </template>
      </ElPopconfirm>

      <ElLink class="mr10" type="primary" @click="openDialog('rename', row)">
        重命名</ElLink
      >
      <ElLink type="primary" @click="handleMove(row)">移动</ElLink>
    </template>
  </Table>

  <ElDialog
    v-model="operationOptions.visible"
    :title="operationOptions[operationOptions.currentType].title"
    width="500"
  >
    <ElInput v-model="operationOptions.filename" />
    <template #footer>
      <ElButton @click="operationOptions.visible = false">取消</ElButton>
      <ElButton
        type="primary"
        @click="operationOptions[operationOptions.currentType].callback"
      >
        确认
      </ElButton>
    </template>
  </ElDialog>

  <Preview
    v-if="previewOptions.visible"
    v-model="previewOptions.visible"
    :file-id="previewOptions.fileInfo.id"
    :filename="previewOptions.fileInfo.filename"
  />

  <MoveDialog
    v-if="moveDialogVisible"
    v-model="moveDialogVisible"
    title="移动至"
    :excludeIds="excludeIds"
    @move="onMoved"
  />
</template>

<script setup>
import { useRoute } from 'vue-router'
import { ref, watch, computed } from 'vue'
import { Toolbar, Table, BreadCrumb } from '@/components'
import UploadItem from './components/uploadItem.vue'
import { useFileUpload } from '@/hooks/useFileUpload'
import { URLS } from '@/constants'
import service from '@/utils/api'
import { PlainMessage } from '@/utils'
import { ElMessageBox } from 'element-plus'
import { BASE_URL } from '@/utils/api'
import Preview from './components/preview.vue'
import MoveDialog from './components/moveDialog.vue'

const KEY_TYPE = {
  ALL: 'all',
  VIDEO: 'video',
  AUDIO: 'audio',
  DOC: 'doc',
  OTHERS: 'others',
  IMAGE: 'image'
}

const route = useRoute()

const key = ref(route.params.key)

watch(
  () => route.params.key,
  newVal => {
    key.value = newVal
    tableOptions.value.options.params.category = newVal
    tableRef.value.refreshGrid()
  }
)

const currentFolderId = computed({
  get: () => tableOptions.value.options.params.parentId,
  set: val => {
    tableOptions.value.options.params.parentId = val
  }
})

const folderStack = ref([])

const visible = ref(false)

const tableOptions = ref({
  columns: [
    {
      type: 'selection'
    },
    {
      key: 'filename',
      title: '文件名',
      minWidth: 260,
      align: 'left',
      slot: 'filename'
    },
    {
      key: 'updatedAt',
      title: '修改时间',
      minWidth: 160,
      align: 'left'
    },
    {
      key: 'size',
      title: '大小',
      minWidth: 160,
      align: 'left',
      render: (h, { row }) => {
        return h('span', row.category !== 'folder' ? row.sizeFormatted : '无')
      }
    },
    {
      key: 'action',
      title: '操作',
      minWidth: 260,
      align: 'left',
      slot: 'action'
    }
  ],
  options: {
    url: URLS.GET_FILES,
    border: false,
    rowStyle: {
      height: '40px',
      lineHeight: '40px'
    },
    params: {
      page: 1,
      size: 10,
      filename: '',
      category: 'all',
      parentId: null
    }
  }
})

const tableRef = ref(null)

const previewOptions = ref({
  fileInfo: null,
  visible: false
})

const {
  uploadMap,
  uploadFile,
  cancelUpload,
  pauseUpload,
  resumeUpload,
  clearUploadRecord
} = useFileUpload({
  autoRetry: false
})

const handleBeforeUpload = async file => {
  visible.value = true
  await uploadFile(file, currentFolderId.value)

  tableRef.value.refreshGrid()
  return false
}

const handleClear = fileId => {
  clearUploadRecord(fileId)
}

const handlePause = (fileId, paused) => {
  paused ? pauseUpload(fileId) : resumeUpload(fileId)
}

const handleCancel = file => {
  cancelUpload(file)
  handleClear(file.id)
}

const handleRetry = fileId => {
  resumeUpload(fileId)
}

const createFolder = async () => {
  await service.post(URLS.CREATE_FOLDER, {
    filename: operationOptions.value.filename,
    parentId: currentFolderId.value
  })

  operationOptions.value.visible = false
  PlainMessage.success('新建成功')
  tableRef.value.refreshGrid()
}

const openFolder = async folder => {
  currentFolderId.value = folder.id

  folderStack.value.push({
    id: folder.id,
    name: folder.filename
  })

  await tableRef.value.refreshGrid()
}

const handleNavigate = id => {
  id !== undefined ? navigateToFolder(id) : navigateToRoot()
}

const navigateToRoot = () => {
  if (currentFolderId.value === null) return

  currentFolderId.value = null
  folderStack.value = []

  tableRef.value.refreshGrid()
}

const navigateToFolder = id => {
  if (id === folderStack.value[folderStack.value.length - 1].id) return

  currentFolderId.value = id
  const index = folderStack.value.findIndex(folder => folder.id === id)
  folderStack.value = folderStack.value.slice(0, index + 1)

  tableRef.value.refreshGrid()
}

const handleBatchDelete = () => {
  const selectedRows = tableRef.value.getSelectionRows()
  if (selectedRows.length === 0) return

  ElMessageBox.confirm('此操作将永久删除该文件, 是否继续?', '提示', {
    confirmButtonText: '确定',
    cancelButtonText: '取消',
    type: 'warning'
  })
    .then(async () => {
      const fileIds = selectedRows.map(row => row.id)
      await service.post(URLS.BATCH_DELETE_FILE, { fileIds })
      tableRef.value.refreshGrid()
      PlainMessage.success('删除成功')
    })
    .catch(() => {})
}

const handleDelete = async id => {
  await service.delete(URLS.DELETE_FILE.replace(':id', id))
  tableRef.value.refreshGrid()
  PlainMessage.success('删除成功')
}

const handleRename = async () => {
  operationOptions.value.visible = true

  await service.patch(
    URLS.RENAME_FILE.replace(':id', operationOptions.value.row.id),
    {
      filename: operationOptions.value.filename
    }
  )

  operationOptions.value.visible = false
  PlainMessage.success('重命名成功')
  tableRef.value.refreshGrid()
}

const operationOptions = ref({
  currentType: 'create', // create、rename
  create: {
    title: '新建文件夹',
    callback: createFolder
  },
  rename: {
    title: '文件重命名',
    callback: handleRename
  },
  row: null,
  filename: '',
  visible: false
})

const openDialog = (currentType, row) => {
  operationOptions.value.currentType = currentType
  operationOptions.value.visible = true
  if (row) {
    operationOptions.value.row = row
    operationOptions.value.filename = row.filename
  } else {
    operationOptions.value.row = null
    operationOptions.value.filename = ''
  }
}

const handleDownload = async row => {
  const token = localStorage.getItem('token')
  window.location.href = `${BASE_URL}${URLS.FILE_DOWNLOAD.replace(
    ':id',
    row.id
  )}?token=${token}`
}

const handlePreview = row => {
  previewOptions.value.visible = true
  previewOptions.value.fileInfo = row
}

const moveDialogVisible = ref(false)
const excludeIds = ref([])

const handleMove = row => {
  moveDialogVisible.value = true
  excludeIds.value = [row.id]
}

const onMoved = async () => {
  await tableRef.value.refreshGrid()
  PlainMessage.success('移动成功')
}

const handleBatchMove = () => {
  const selectedRows = tableRef.value.getSelectionRows()
  if (selectedRows.length === 0) return

  moveDialogVisible.value = true
  excludeIds.value = selectedRows.map(row => row.id)
}
</script>

<style scoped>
@import '@/assets/file.list.css';

.file-list {
  height: 90%;
}

.upload-popover {
  padding: 10px;
}

.upload-header {
  font-size: 16px;
  font-weight: bold;
  padding: 10px 0;
}

.upload-subtitle {
  color: #909399;
  font-size: 12px;
  font-weight: normal;
}

.upload-divider {
  height: 1px;
  background-color: #e4e7ed;
  margin: 10px 0;
}

.upload-body {
  min-height: 200px;
}

.mr10 {
  margin-right: 10px;
}

:deep(.el-icon) {
  vertical-align: middle;
}
</style>
